using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Rensoft.CRM.Client.AccountsAPI;

namespace Rensoft.CRM.Client.Editors
{
    public partial class BaseEditor : Form
    {
        private bool saving;
        private bool loading;
        private EditorMode mode;
        private SaveMode saveMode;
        private Program program;

        public Program Program
        {
            get { return program; }
        }

        public EditorMode Mode
        {
            get { return mode; }
        }

        public bool Loading
        {
            get { return loading; }
        }

        public bool Saving
        {
            get { return saving; }
        }

        public event EventHandler LoadComplete;
        public event EventHandler SaveComplete;

        /// <summary>
        /// Parameterless constructor for forms designer.
        /// </summary>
        protected BaseEditor()
        {
            InitializeComponent();
        }

        protected BaseEditor(Program program) : this()
        {
            Button closeButton = new Button();
            closeButton.DialogResult = DialogResult.Cancel;
            closeButton.Click += new EventHandler(closeButton_Click);
            CancelButton = closeButton;

            this.program = program;

            LoadComplete += new EventHandler(OnLoadComplete);
            SaveComplete += new EventHandler(OnSaveComplete);
        }

        protected virtual void OnLoadComplete(object sender, EventArgs e) { }
        protected virtual void OnSaveComplete(object sender, EventArgs e) { }

        protected virtual void PerformClear() { }
        protected virtual void PerformSave(DoWorkEventArgs e) { }
        protected virtual void PerformLoad(DoWorkEventArgs e) { }

        protected void SetMode(EditorMode mode)
        {
            this.mode = mode;
        }

        void closeButton_Click(object sender, EventArgs e)
        {
            Close();
        }

        protected virtual void SaveAsync(SaveMode mode)
        {
            saving = true;
            saveMode = mode;
            UseWaitCursor = true;
            saveBackgroundWorker.RunWorkerAsync();
        }

        private void saveBackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            AccountsService service = AccountsService.CreateInstance();
            MethodInvoker testMethod = new MethodInvoker(service.Test);

            if (program.ConfirmConnection(service, testMethod))
            {
                PerformSave(e);
            }
        }

        protected virtual void OnSaveRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            saving = false;
            if (e.Error != null)
            {
                throw e.Error;
            }
            else if (!e.Cancelled)
            {
                switch (saveMode)
                {
                    case SaveMode.SaveNew:
                        // Perform quick actions in this thread.
                        PerformClear();

                        // Load complex fields in separate thread.
                        LoadAsync();
                        break;

                    case SaveMode.SaveClose:
                        Close();
                        break;
                }
            }

            SaveComplete(this, EventArgs.Empty);
            UseWaitCursor = false;
        }

        protected virtual void OnSaveClose(object sender, EventArgs e)
        {
            SaveAsync(SaveMode.SaveClose);
        }

        protected virtual void OnSaveNew(object sender, EventArgs e)
        {
            SaveAsync(SaveMode.SaveNew);
        }

        private void saveToolStripButton_Click(object sender, EventArgs e)
        {
            SaveAsync(SaveMode.SaveOnly);
        }

        public void LoadAsync()
        {
            // Parent to wait while this loads.
            program.UseWaitCursor = true;
            loading = true;

            // Prepares form for view before shown.
            loadBackgroundWorker.RunWorkerAsync();
        }

        private void loadBackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            AccountsService service = AccountsService.CreateInstance();
            MethodInvoker testMethod = new MethodInvoker(service.Test);

            if (Program.ConfirmConnection(service, testMethod))
            {
                PerformLoad(e);
            }
            else
            {
                e.Cancel = true;
            }
        }

        private void loadBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            loading = false;

            if (e.Cancelled)
            {
                this.Close();
            }
            else if (e.Error != null)
            {
                throw e.Error;
            }
            else
            {
                LoadComplete(this, EventArgs.Empty);
            }

            // Parent finished waiting.
            program.UseWaitCursor = false;
        }

        protected void InitializeAccountComboBox(ComboBox comboBox, AccountType types)
        {
            AccountsService service = AccountsService.CreateInstance();
            Account[] accountArray = service.AccountFetchByType(types);

            List<AccountComboItem> list = new List<AccountComboItem>();
            foreach (Account account in accountArray)
            {
                list.Add(new AccountComboItem(account));
            }

            comboBox.DataSource = list;
            comboBox.ValueMember = "Value";
            comboBox.DisplayMember = "Display";
        }

        protected void InitializeCurrencyComboBox(ComboBox comboBox)
        {
            List<CurrencyComboItem> list = new List<CurrencyComboItem>();
            list.Add(new CurrencyComboItem("GBP", "Pounds Sterling (GBP)"));
            list.Add(new CurrencyComboItem("GBP", "US Dollars (USD)"));
            comboBox.DataSource = list;
            comboBox.SelectedIndex = 0;
        }

        protected override void OnClosing(CancelEventArgs e)
        {
            if (saveBackgroundWorker.IsBusy)
            {
                e.Cancel = true;
                return;
            }

            loadBackgroundWorker.CancelAsync();
            base.OnClosing(e);
        }

        protected void AddToolStripItem(ToolStripItem item, bool visible)
        {
            EditorToolStrip.Items.Add(item);
            item.Visible = visible;
        }
    }

    internal class CurrencyComboItem
    {
        private string currency;
        private string description;

        public string Value
        {
            get { return currency; }
        }

        public string Display
        {
            get { return description; }
        }

        public CurrencyComboItem(string currency, string description)
        {
            this.currency = currency;
            this.description = description;
        }
    }

    internal class AccountComboItem
    {
        private Account account;

        public Account Value
        {
            get { return account; }
        }

        public string Display
        {
            get { return account.Code + " - " + account.Title; }
        }

        public AccountComboItem(Account account)
        {
            this.account = account;
        }
    }

    public enum EditorMode
    {
        Create, Modify
    }

    public enum SaveMode
    {
        SaveOnly, SaveNew, SaveClose
    }
}